package com.ants.modules.ArticleView.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.alibaba.fastjson.JSONObject;
import com.ants.common.annotation.AutoLog;
import com.ants.common.annotation.RateLimiter;
import com.ants.common.constant.CacheConstant;
import com.ants.common.exception.AntsException;
import com.ants.common.utils.*;
import com.ants.modules.ArticleManage.entity.ArticleContent;
import com.ants.modules.ArticleManage.service.ArticleContentService;
import com.ants.modules.compressUsageLog.service.CompressUsageLogService;
import com.ants.modules.utils.ElasticSearchUtils;
import com.ants.common.system.api.ISysBaseAPI;
import com.ants.common.system.query.QueryGenerator;
import com.ants.common.system.result.Result;
import com.ants.common.system.vo.LoginUser;
import com.ants.modules.ArticleManage.dto.ArticleManageDto;
import com.ants.modules.ArticleManage.entity.ArticleLikeCollection;
import com.ants.modules.ArticleManage.entity.ArticleManage;
import com.ants.modules.ArticleManage.service.ArticleLikeCollectionService;
import com.ants.modules.ArticleManage.service.ArticleManageService;
import com.ants.modules.ArticleManage.vo.ArticleManageVo;
import com.ants.modules.ArticleView.vo.PersonalHomeInfoVo;
import com.ants.modules.articleFavorites.entity.ArticleFavoritesSub;
import com.ants.modules.articleFavorites.service.ArticleFavoritesSubService;
import com.ants.modules.articleFollow.entity.ArticleFollow;
import com.ants.modules.articleFollow.service.ArticleFollowService;
import com.ants.modules.articleFollow.vo.ArticleFollowVo;
import com.ants.modules.articleLable.entity.ArticleLable;
import com.ants.modules.articleLable.service.ArticleLableService;
import com.ants.modules.articleSort.entity.ArticleSort;
import com.ants.modules.articleSort.service.ArticleSortService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * TODO
 * Author Chen
 * Date   2021/9/7 18:44
 */

@Slf4j
@Api(tags = "文章管理")
@RestController
@RequestMapping("/articleView")
public class ArticleViewController {

    @Autowired
    ArticleManageService articleManageService;
    @Autowired
    ArticleContentService articleContentService;
    @Autowired
    ElasticSearchUtils elasticSearchUtils;
    @Autowired
    ArticleLikeCollectionService articleLikeCollectionService;
    @Autowired
    ISysBaseAPI sysBaseAPI;
    @Autowired
    ArticleFavoritesSubService articleFavoritesSubService;
    @Autowired
    ArticleFollowService articleFollowService;
    @Autowired
    ArticleSortService articleSortService;
    @Autowired
    ArticleLableService articleLableService;
    @Autowired
    ElasticsearchClient restHighLevelClient;
    @Autowired
    CompressUsageLogService compressUsageLogService;


    @AutoLog(value = "查询文章")
    @ApiOperation(value = "查询文章", notes = "查询文章")
    @RateLimiter
    @GetMapping("/getArticleList")
    public Result<?> getArticleList(ArticleManage articleManage,
                                    @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                    HttpServletRequest req) throws IOException {
        String username = articleManage.getCreateBy();
        String columu = req.getParameter("column");
        SearchRequest.Builder builder = new SearchRequest.Builder();
        builder.index(CacheConstant.ES_INDEX);
        if (StrUtil.isNotBlank(username)) {
            builder.query(queryBuilder -> queryBuilder
                    .bool(boolQueryBuilder -> boolQueryBuilder
                            .must(queryBuilder2 -> queryBuilder2
                                    .term(matchQueryBuilder -> matchQueryBuilder
                                            .field("createBy").value(username))
                            )
                            .must(queryBuilder2 -> queryBuilder2
                                    .term(rangeQueryBuilder -> rangeQueryBuilder
                                            .field("delFlag").value(0))
                            )
                    ));
        } else {
            builder.query(q -> q.term(t -> t
                    .field("delFlag")
                    .value(0)
            ));
        }
        builder.sort(sort -> sort
                        .field(f -> f
                                .field(columu)
                                .order(SortOrder.Desc)
                        )
                )
                .source(source -> source
                        .filter(f -> f
                                .excludes("html", "content")
                        )
                )
                .from((pageNo - 1) * pageSize).size(pageSize);
        SearchResponse<ArticleManageDto> search = restHighLevelClient.search(builder.build(),
                ArticleManageDto.class);
        List<ArticleManageDto> result = new ArrayList<>();
        for (Hit<ArticleManageDto> hit : search.hits().hits()) {
            ArticleManageDto source = hit.source();
            result.add(source);
        }
        IPage<ArticleManageDto> page = new Page<>();
        page.setRecords(result);
        page.setTotal(search.hits().total().value());
        return Result.ok(page);
    }

    @AutoLog(value = "查询推荐文章")
    @ApiOperation(value = "查询推荐文章", notes = "查询推荐文章")
    @RateLimiter
    @GetMapping("/recommend")
    public Result<?> recommend() {
        List<Map<String, Object>> mapList = articleManageService.recommend();
        return Result.ok(mapList);
    }

    /**
     * @return
     * @功能：查询浏览量最多的前N篇文章
     */
    @AutoLog(value = "查询浏览量最多的前N篇文章")
    @ApiOperation(value = "查询浏览量最多的前N篇文章", notes = "查询浏览量最多的前N篇文章")
    @GetMapping("/getHotArticle")
    @RateLimiter
    public Result<?> getHotArticle(@RequestParam(required = false) String username,
                                   @RequestParam(name = "hotNum", defaultValue = "4") Integer hotNum) {
        LambdaQueryWrapper<ArticleManage> lqw = new LambdaQueryWrapper<>();
        lqw.orderByDesc(ArticleManage::getViewsNum);
        lqw.eq(ArticleManage::getDelFlag, "0");
        lqw.last("limit " + hotNum);
        if (StrUtil.isNotBlank(username)) {
            lqw.eq(ArticleManage::getCreateBy, username);
        }
        List<ArticleManage> list = articleManageService.list(lqw);
        return Result.ok(list);
    }

    /**
     * @return
     * @功能：查询所有分类
     */
    @AutoLog(value = "查询所有分类")
    @ApiOperation(value = "查询所有分类", notes = "查询所有分类")
    @GetMapping("/initArticleSort")
    @RateLimiter
    public Result<?> initArticleSort() {
//        List<ArticleManageVo> list = articleManageService.initArticleSort();
        List<ArticleSort> list = articleSortService.list();
        return Result.ok(list);
    }

    /**
     * @return
     * @功能：查询所有标签
     */
    @AutoLog(value = "查询所有标签")
    @ApiOperation(value = "查询所有标签", notes = "查询所有标签")
    @GetMapping("/initArticleLable")
    @RateLimiter
    public Result<?> initArticleLable() {
//        List<ArticleManageVo> list = articleManageService.initArticleLable();
        List<ArticleLable> list = articleLableService.list();
        return Result.ok(list);
    }

    /**
     * @return
     * @功能：查询标签发布文章数
     */
    @AutoLog(value = "查询标签发布文章数")
    @ApiOperation(value = "查询标签发布文章数", notes = "查询标签发布文章数")
    @GetMapping("/getLableStatistics")
    @RateLimiter
    public Result<?> getLableStatistics(@RequestParam String username) {
        List<ArticleManageVo> list = articleManageService.initArticleLable(username);
        return Result.ok(list);
    }

    /**
     * @param id
     * @return
     * @功能：查询文章 根据id
     */
    @AutoLog(value = "查询指定文章")
    @ApiOperation(value = "查询指定文章", notes = "查询指定文章")
    @GetMapping("/getArticleById")
    @RateLimiter
    public Result<?> getArticleById(@RequestParam String id) {
        List<ArticleManage> list = new ArrayList<>();
        ArticleManage byId = articleManageService.getById(id);
        if (byId == null) {
            return Result.ok();
        }
        LambdaQueryWrapper<ArticleContent> contentlqw = new LambdaQueryWrapper<>();
        contentlqw.eq(ArticleContent::getMainId, id);
        ArticleContent articleContent = articleContentService.getOne(contentlqw);
        byId.setHtml(articleContent.getHtml());
        boolean login = StpUtil.isLogin();
        LoginUser userByName = sysBaseAPI.getUserByName(byId.getCreateBy());
        byId.setUserAvatar(userByName.getAvatar());
        if (login) {
            String username = StpUtil.getLoginIdAsString();// 查询当前会话账号id, 并转化为`String`类型
            LambdaQueryWrapper<ArticleLikeCollection> lqw = new LambdaQueryWrapper<>();
            lqw.eq(ArticleLikeCollection::getUsername, username)
                    .eq(ArticleLikeCollection::getArticleId, id);
            ArticleLikeCollection articleLikeCollection = articleLikeCollectionService.getOne(lqw);
            if (articleLikeCollection != null) {
                byId.setIsLikes("1");
            }
            LambdaQueryWrapper<ArticleFavoritesSub> lqw2 = new LambdaQueryWrapper<>();
            lqw2.eq(ArticleFavoritesSub::getCreateBy, username)
                    .eq(ArticleFavoritesSub::getArticleId, id);
            ArticleFavoritesSub articleFavoritesSub = articleFavoritesSubService.getOne(lqw2);
            if (articleFavoritesSub != null) {
                byId.setIsCollect("1");
            }
            LambdaQueryWrapper<ArticleFollow> lqw3 = new LambdaQueryWrapper<>();
            lqw3.eq(ArticleFollow::getUsername, byId.getCreateBy())
                    .eq(ArticleFollow::getCreateBy, username);
            ArticleFollow articleFollow = articleFollowService.getOne(lqw3);
            if (articleFollow != null) {
                byId.setIsFollow(false);
            } else {
                byId.setIsFollow(true);
            }
        } else {
            byId.setIsFollow(true);
        }
        IPage<ArticleManage> page = new Page<>();
        list.add(byId);
        page.setRecords(list);
        return Result.ok(page);
    }

    /**
     * @return
     * @功能：归档 根据id
     */
    @AutoLog(value = "根据时间轴分类统计文章")
    @ApiOperation(value = "根据时间轴分类统计文章", notes = "根据时间轴分类统计文章")
    @GetMapping("/articleGroupByCreateTime")
    @RateLimiter
    public Result<?> articleGroupByCreateTime() {
        List<Map<String, Object>> listMaps = articleManageService.articleGroupByCreateTime(null);
        listMaps.forEach(e -> {
            String createMonth = String.valueOf(e.get("createMonth"));
            List<ArticleManage> list = articleManageService.getArticleByTime(createMonth, null);
            e.put("data", list);
        });
        return Result.ok(listMaps);
    }

    /**
     * @return
     * @功能：查询文章 根据id
     */
    @AutoLog(value = "根据时间查询文章")
    @ApiOperation(value = "根据时间查询文章", notes = "根据时间查询文章")
    @GetMapping("/getArticleByTime")
    @RateLimiter
    public Result<?> getArticleByTime(@RequestParam String time) {
        List<ArticleManage> list = articleManageService.getArticleByTime(time, null);
        IPage<ArticleManage> page = new Page<>();
        page.setRecords(list);
        return Result.ok(page);
    }

    /**
     * @return
     * @功能：全文检索 根据标题、内容检索文章
     */
    @AutoLog(value = "全文检索文章")
    @ApiOperation(value = "全文检索文章", notes = "全文检索文章")
    @GetMapping("/searchAllActive")
    @RateLimiter
    public Result<?> searchAllActive(@RequestParam String value) throws IOException {
        SearchRequest.Builder builder = new SearchRequest.Builder();
        builder.index(CacheConstant.ES_INDEX)
                .query(q -> q.term(t -> t
                        .field("delFlag")
                        .value(0)
                ))
                .query(q -> q.multiMatch(m -> m.
                        fields("title", "abstractText")
                        .query(value)))
                .highlight(h -> h
                        .fields("title", highlightFieldBuilder -> highlightFieldBuilder)
                        .fields("abstractText", highlightFieldBuilder -> highlightFieldBuilder)
                        .preTags("<font color='red'>")
                        .postTags("</font>")
                )
                .sort(sort -> sort
                        .field(f -> f
                                .field("publishTime")
                                .order(SortOrder.Desc)
                        )
                )
                .source(source -> source
                        .filter(f -> f
                                .excludes("html", "content")
                        )
                );
        SearchResponse<ArticleManageDto> search = restHighLevelClient.search(builder.build(),
                ArticleManageDto.class);
        List<ArticleManageDto> result = new ArrayList<>();
        for (Hit<ArticleManageDto> hit : search.hits().hits()) {
            ArticleManageDto source = hit.source();
            for (Map.Entry<String, List<String>> entry : hit.highlight().entrySet()) {
                ReflectUtil.setFieldValue(source, entry.getKey(), entry.getValue().get(0));
            }
            result.add(source);
        }
        IPage<ArticleManageDto> page = new Page<>();
        page.setRecords(result);
        page.setTotal(search.hits().total().value());
        return Result.ok(page);
    }

    /**
     * 点赞
     *
     * @param articleLikeCollection
     * @return
     */
    @AutoLog(value = "点赞")
    @ApiOperation(value = "点赞", notes = "点赞")
    @PostMapping("/likeCollection")
    @RateLimiter
    @Transactional(rollbackFor = Exception.class)
    public Result<?> likeCollection(@RequestBody ArticleLikeCollection articleLikeCollection) {
        String username = StpUtil.getLoginIdAsString();// 查询当前会话账号id, 并转化为`String`类型
        articleLikeCollection.setUsername(username);
        articleLikeCollectionService.save(articleLikeCollection);
        ArticleManage byId = articleManageService.getById(articleLikeCollection.getArticleId());
        byId.setLikesNum(byId.getLikesNum() + 1);
        articleManageService.updateById(byId);
        return Result.ok();
    }

    /**
     * 取消点赞
     *
     * @param articleId
     * @return
     */
    @AutoLog(value = "取消点赞")
    @ApiOperation(value = "取消点赞", notes = "取消点赞")
    @DeleteMapping("/cancelLikeCollection")
    @RateLimiter
    @Transactional(rollbackFor = Exception.class)
    public Result<?> cancelLikeCollection(@RequestParam String articleId) {
        String username = StpUtil.getLoginIdAsString();// 查询当前会话账号id, 并转化为`String`类型
        LambdaQueryWrapper<ArticleLikeCollection> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ArticleLikeCollection::getUsername, username)
                .eq(ArticleLikeCollection::getArticleId, articleId);
        articleLikeCollectionService.remove(lqw);
        ArticleManage byId = articleManageService.getById(articleId);
        byId.setLikesNum(byId.getLikesNum() - 1);
        articleManageService.updateById(byId);
        return Result.ok();
    }


    @AutoLog(value = "浏览数+1")
    @ApiOperation(value = "浏览数+1", notes = "浏览数+1")
    @GetMapping("/recordViewsNum")
    @RateLimiter
    public Result<Object> recordViewsNum(@RequestParam String id) {
        articleManageService.updateViewsNum(id);
        ArticleManageDto map = articleManageService.getArticleToESById(id);
        if (ObjectUtil.isNull(map)) {
            return Result.ok();
        }
        elasticSearchUtils.updateDocument(CacheConstant.ES_INDEX, id, map);
        return Result.ok();
    }

    /**
     * 个人主页-个人信息+文章信息
     *
     * @return
     */
    @AutoLog(value = "个人主页查询相关信息")
    @ApiOperation(value = "个人主页查询相关信息", notes = "个人主页查询相关信息")
    @GetMapping("/getPersonalHomeInfo")
    @RateLimiter
    public Result<?> getPersonalHomeInfo(@RequestParam String username) {

        LoginUser loginUser = sysBaseAPI.getUserByName(username);

        PersonalHomeInfoVo personalHomeInfoVo = new PersonalHomeInfoVo();
        personalHomeInfoVo.setUserAvatar(loginUser.getAvatar());
        personalHomeInfoVo.setUsername(loginUser.getUsername());
        personalHomeInfoVo.setRealname(loginUser.getRealname());
        personalHomeInfoVo.setJoinTime(DateUtil.formatBetween(loginUser.getCreateTime(), DateUtil.date(), BetweenFormatter.Level.MINUTE));
        LambdaQueryWrapper<ArticleManage> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ArticleManage::getCreateBy, username);
        lqw.eq(ArticleManage::getDelFlag, 0);
        List<ArticleManage> list = articleManageService.list(lqw);
        personalHomeInfoVo.setCreateTime(loginUser.getCreateTime());

        LambdaQueryWrapper<ArticleLikeCollection> alcLqw = new LambdaQueryWrapper<>();
        alcLqw.eq(ArticleLikeCollection::getUsername, username);
        long likeNum = articleLikeCollectionService.count(alcLqw);
        personalHomeInfoVo.setLikesNum(likeNum);

        LambdaQueryWrapper<ArticleFavoritesSub> afsLqw = new LambdaQueryWrapper<>();
        afsLqw.eq(ArticleFavoritesSub::getCreateBy, username);
        long collectNum = articleFavoritesSubService.count(afsLqw);
        personalHomeInfoVo.setCollectNum(collectNum);
        personalHomeInfoVo.setArticleNum(list.size());
        return Result.ok(personalHomeInfoVo);
    }

    /**
     * 个人主页-查询文章
     *
     * @return
     */

    @AutoLog(value = "个人主页-查询文章")
    @ApiOperation(value = "个人主页-查询文章", notes = "个人主页-查询文章")
    @GetMapping("/getPersonalHomelist")
    @RateLimiter
    public Result<?> getPersonalHomelist(@RequestParam String sortType,
                                         @RequestParam String username) {
        LambdaQueryWrapper<ArticleManage> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ArticleManage::getCreateBy, username);
        if ("1".equals(sortType)) {
            lqw.orderByDesc(ArticleManage::getCreateTime);
        } else if ("2".equals(sortType)) {
            lqw.orderByDesc(ArticleManage::getViewsNum);
        } else if ("3".equals(sortType)) {
            lqw.orderByDesc(ArticleManage::getLikesNum);
        } else {
            lqw.orderByDesc(ArticleManage::getCollectNum);
        }
        List<ArticleManage> list = articleManageService.list(lqw);
        IPage<ArticleManage> page = new Page<>();
        page.setRecords(list);

        return Result.ok(page);
    }

    /**
     * 个人主页-收藏-展示个人收藏的文章
     *
     * @param username
     * @return
     */
    @AutoLog(value = "个人主页-查询收藏的文章")
    @ApiOperation(value = "个人主页-查询收藏的文章", notes = "个人主页-查询收藏的文章")
    @GetMapping("/getPersonMyFavoritesList")
    @RateLimiter
    public Result<?> getPersonMyFavoritesList(@RequestParam String username,
                                              @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                              @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        LambdaQueryWrapper<ArticleFavoritesSub> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ArticleFavoritesSub::getCreateBy, username);
        Page<ArticleFavoritesSub> page = new Page<ArticleFavoritesSub>(pageNo, pageSize);
        Page<ArticleFavoritesSub> pageList = articleFavoritesSubService.page(page, lqw);
        for (ArticleFavoritesSub articleFavoritesSub : pageList.getRecords()) {
            ArticleManage articleManage = articleManageService.getById(articleFavoritesSub.getArticleId());
            articleFavoritesSub.setArticleManage(articleManage);
        }
        return Result.ok(pageList);
    }

    /**
     * 个人主页-点赞-展示个人点赞的文章
     *
     * @param username
     * @return
     */
    @AutoLog(value = "个人主页-查询点赞的文章")
    @ApiOperation(value = "个人主页-查询点赞的文章", notes = "个人主页-查询点赞的文章")
    @GetMapping("/getPersonLikeList")
    @RateLimiter
    public Result<?> getPersonLikeList(@RequestParam String username,
                                       @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                       @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        LambdaQueryWrapper<ArticleLikeCollection> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ArticleLikeCollection::getUsername, username);
        Page<ArticleLikeCollection> page = new Page<ArticleLikeCollection>(pageNo, pageSize);
        Page<ArticleLikeCollection> pageList = articleLikeCollectionService.page(page, lqw);
        for (ArticleLikeCollection articleLikeCollection : pageList.getRecords()) {
            ArticleManage articleManage = articleManageService.getById(articleLikeCollection.getArticleId());
            articleLikeCollection.setArticleManage(articleManage);
        }
        return Result.ok(pageList);
    }

    /**
     * 个人主页-关注
     *
     * @param username
     * @return
     */
    @AutoLog(value = "个人主页-查询关注文章")
    @ApiOperation(value = "个人主页-查询关注文章", notes = "个人主页-查询关注文章")
    @GetMapping("/getPersonFollowList")
    @RateLimiter
    public Result<?> getPersonFollowList(@RequestParam String username) {
        LambdaQueryWrapper<ArticleFollow> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ArticleFollow::getCreateBy, username);
        List<ArticleFollow> list = articleFollowService.list(lqw);
        List<ArticleFollowVo> results = new ArrayList<>();
        ArticleFollowVo articleFollowVo = null;
        for (ArticleFollow articleFollow : list) {
            articleFollowVo = new ArticleFollowVo();
            LambdaQueryWrapper<ArticleManage> lqw2 = new LambdaQueryWrapper<>();
            lqw2.eq(ArticleManage::getCreateBy, articleFollow.getUsername());
            List<ArticleManage> articleManageList = articleManageService.list(lqw2);
            Integer collectNum = articleManageList.stream().collect(Collectors.summingInt(ArticleManage::getCollectNum));
            Integer viewNum = articleManageList.stream().collect(Collectors.summingInt(ArticleManage::getViewsNum));
            Integer likeNum = articleManageList.stream().collect(Collectors.summingInt(ArticleManage::getLikesNum));
            LoginUser loginUser = sysBaseAPI.getUserByName(articleFollow.getUsername());
            articleFollowVo.setUsername(articleFollow.getUsername());
            articleFollowVo.setUserAvatar(loginUser.getAvatar());
            articleFollowVo.setCollectNum(collectNum);
            articleFollowVo.setViewsNum(viewNum);
            articleFollowVo.setLikesNum(likeNum);
            articleFollowVo.setArticleNum(articleManageList.size());
            articleFollowVo.setJoinTime(DateUtil.formatBetween(loginUser.getCreateTime(), DateUtil.date(), BetweenFormatter.Level.MINUTE));
            results.add(articleFollowVo);
        }
        IPage<ArticleFollowVo> page = new Page<>();
        page.setRecords(results);
        return Result.ok(page);
    }


    /**
     * @return
     * @功能：根据分类查找文章
     */
    @AutoLog(value = "根据分类查找文章")
    @ApiOperation(value = "根据分类查找文章", notes = "根据分类查找文章")
    @GetMapping("/getArticleBySortId")
    @RateLimiter
    public Result<?> getArticleBySortId(@RequestParam String id,
                                        @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                        @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {

        QueryWrapper<ArticleManage> qw = new QueryWrapper<>();
        QueryGenerator.assM2MQueryWrapper(qw, "article_sort", id);
        Page<ArticleManage> page = new Page<>(pageNo, pageSize);
        Page<ArticleManage> pageList = articleManageService.page(page, qw);
        return Result.ok(pageList);
    }

    /**
     * @return
     * @功能：根据标签查找文章
     */
    @AutoLog(value = "根据标签查找文章")
    @ApiOperation(value = "根据标签查找文章", notes = "根据标签查找文章")
    @GetMapping("/getArticleByLableId")
    @RateLimiter
    public Result<?> getArticleByLableId(@RequestParam String id,
                                         @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                         @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        QueryWrapper<ArticleManage> qw = new QueryWrapper<>();
        QueryGenerator.assM2MQueryWrapper(qw, "article_lable", id);
        Page<ArticleManage> page = new Page<>(pageNo, pageSize);
        Page<ArticleManage> pageList = articleManageService.page(page, qw);
        return Result.ok(pageList);
    }


    /**
     * @return
     * @功能：根据id查找分类
     */
    @AutoLog(value = "查找指定分类")
    @ApiOperation(value = "查找指定分类", notes = "查找指定分类")
    @GetMapping("/getArticleSortById")
    @RateLimiter
    public Result<?> getArticleSortById(@RequestParam String id) {
        ArticleSort entity = articleSortService.getById(id);
        return Result.ok(entity);
    }

    /**
     * @return
     * @功能：根据id查找标签
     */
    @AutoLog(value = "查找指定标签")
    @ApiOperation(value = "查找指定标签", notes = "查找指定标签")
    @GetMapping("/getArticleLableById")
    @RateLimiter
    public Result<?> getArticleLableById(@RequestParam String id) {
        ArticleLable entity = articleLableService.getById(id);
        return Result.ok(entity);
    }

//    /**
//     * @return
//     * @功能：查询壁纸
//     */
//    @AutoLog(value = "查找指定标签")
//    @ApiOperation(value = "查找指定标签", notes = "查找指定标签")
//    @GetMapping("/getMeiTu")
//    @RateLimiter
//    public Result<?> getMeiTu(@RequestParam String id) {
//        ArticleLable entity = articleLableService.getById(id);
//        return Result.ok(entity);
//    }

    /**
     * @return
     * @功能：查询壁纸分类字典
     */
    @AutoLog(value = "查询壁纸分类")
    @ApiOperation(value = "查询壁纸分类", notes = "查询壁纸分类")
    @GetMapping("/getWallpaperType")
    @RateLimiter
    public Result<?> getWallpaperType() {
//        List<DictModel> wallpaperType = sysBaseAPI.queryDictItemsByCode("wallpaper_type");
        JSONObject jsonObject = RestUtil.get("http://wallpaper.apc.360.cn/index.php?c=WallPaperAndroid&a=getAllCategories");
        return Result.ok(jsonObject.getJSONArray("data"));
    }


    /**
     * @return
     * @功能： java检测百度是否收录网站url
     */
    @GetMapping("/checkBaiduIncludeUrl")
    @RateLimiter
    public Result<?> checkBaiduIncludeUrl(@RequestParam String id) {
        String html = CheckBaiduIncludeUrlUtil.checkBaiduInclude("https://www.wxmin.cn/articleDetails/" + id);
        if (!"".equals(html)) {
            Document doc = Jsoup.parse(html);
            Element element = doc.getElementsByClass("content_none").first();
            if (null == element) {
                return Result.ok("百度已经收录该网址");
            } else {
                return Result.error(200, "百度没有收录该网址");
            }
        }
        return Result.error(200, "百度没有收录该网址");
    }


    @AutoLog(value = "归档-折线图")
    @ApiOperation(value = "归档-折线图", notes = "归档-折线图")
    @RateLimiter
    @GetMapping("/articleStatisticsLineChart")
    public Result<?> articleStatisticsLineChart(@RequestParam String month) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        DateTime beginOfMonth = new DateTime();
        DateTime endOfMonth = new DateTime();
        try {
            if (StrUtil.isNotBlank(month)) {
                date = sdf.parse(month + "-01");
                beginOfMonth = DateUtil.beginOfMonth(date);
                endOfMonth = DateUtil.endOfMonth(date);
            } else {
                date = sdf.parse(DateUtil.today());
                beginOfMonth = DateUtil.beginOfMonth(new Date());
                endOfMonth = DateUtil.endOfMonth(new Date());
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int actualMaximum = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= actualMaximum; i++) {
            String b = "0";
            if (i < 10) {
                sb.append(" UNION SELECT '" + 0 + i + "' `month`,0 articleNum,0 viewsNum,0 likesNum,0 collectNum");
            } else {
                sb.append(" UNION SELECT '" + i + "' `month`,0 articleNum,0 viewsNum,0 likesNum,0 collectNum");
            }
        }
        String startTime = DateUtil.formatDateTime(beginOfMonth);
        String endTime = DateUtil.formatDateTime(endOfMonth);
        List<Map<String, Object>> mapList = articleManageService.articleStatisticsLineChart(null, startTime, endTime, sb.toString());
        return Result.ok(mapList);
    }

    @AutoLog(value = "归档-头部统计")
    @ApiOperation(value = "归档-头部统计", notes = "归档-头部统计")
    @RateLimiter
    @GetMapping("/statisticsTopNum")
    public Result<?> statisticsTopNum(@RequestParam(required = false) String username) {
        LambdaQueryWrapper<ArticleManage> articleManagelqw = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<ArticleLikeCollection> articleLikeCollectionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<ArticleSort> articleSortLambdaQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<ArticleLable> articleLableLambdaQueryWrapper = new LambdaQueryWrapper<>();

        if (StrUtil.isNotBlank(username)) {
            articleManagelqw.eq(ArticleManage::getCreateBy, username);
            articleLikeCollectionLambdaQueryWrapper.eq(ArticleLikeCollection::getCreateBy, username);
            articleSortLambdaQueryWrapper.eq(ArticleSort::getCreateBy, username);
            articleLableLambdaQueryWrapper.eq(ArticleLable::getCreateBy, username);
        }
        Map<String, Object> map = new HashMap<>();
        long articleCount = articleManageService.count(articleManagelqw);
        long likeCount = articleLikeCollectionService.count(articleLikeCollectionLambdaQueryWrapper);
        long sortCount = articleSortService.count(articleSortLambdaQueryWrapper);
        long lableCount = articleLableService.count(articleLableLambdaQueryWrapper);
        int viewcount = articleManageService.getViewNumSum(username);
        map.put("articleCount", articleCount);
        map.put("likeCount", likeCount);
        map.put("sortCount", sortCount);
        map.put("lableCount", lableCount);
        map.put("viewcount", viewcount);
        return Result.ok(map);
    }

    @AutoLog(value = "分类-分类统计")
    @ApiOperation(value = "分类-分类统计", notes = "分类-分类统计")
    @RateLimiter
    @GetMapping("/sortStatisticsChart")
    public Result<?> sortStatisticsChart() {
        List<Map<String, Object>> mapList = articleManageService.sortStatisticsChart();
        return Result.ok(mapList);
    }

    @AutoLog(value = "阅读量前Top5推荐")
    @ApiOperation(value = "阅读量前Top5推荐", notes = "阅读量前Top5推荐")
    @RateLimiter
    @GetMapping("/getArticleTop5ByViewNum")
    public Result<?> getArticleTop5ByViewNum() {
        List<Map<String, Object>> mapList = articleManageService.getArticleTop5ByViewNum();
        return Result.ok(mapList);
    }

    @AutoLog(value = "发布文章数占比前5的分类")
    @ApiOperation(value = "发布文章数占比前5的分类", notes = "发布文章数占比前5的分类")
    @GetMapping("/getSortTop5")
    @RateLimiter
    public Result<?> getSortTop5() {
        List<Map<String, Object>> mapList = articleManageService.getSortTop5();
        return Result.ok(mapList);
    }

    @RateLimiter
    @GetMapping("/getUserInfoByArticleId")
    public Result<?> getUserInfoByArticleId(@RequestParam String id) {
        Map<String, String> map = articleManageService.getUserInfoByArticleId(id);
        return Result.ok(map);
    }

    @AutoLog(value = "查询文章详情")
    @ApiOperation(value = "查询文章详情", notes = "查询文章详情")
    @RateLimiter
    @GetMapping("/getArticleDetailsTitle")
    public Result<?> getArticleDetailsTitle(@RequestParam String id) {
        ArticleManage entity = articleManageService.getById(id);
        if (entity == null) {
            return Result.error("文章不存在！");
        }
        return Result.ok(entity.getTitle());
    }

    @RateLimiter
    @GetMapping("/getAntsSystemConfig")
    public Result<?> getAntsSystemConfig() {
        Map<String, Object> map = sysBaseAPI.getAntsSystemConfig();
        return Result.ok(map);
    }

    @Value(value = "${ants.path.upload}")
    private String uploadpath;

    @RateLimiter
    @PostMapping("/compressUpload")
    public Result<?> compressUpload(@RequestParam Double radioValue, HttpServletRequest request, HttpServletResponse response) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象

        String bizPath = "fileTools" + File.separator + request.getParameter("biz");

        InputStream inputStream = mf.getInputStream();
        String filePath = uploadpath + File.separator + bizPath;
        String fileName = mf.getOriginalFilename();
        fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "_" + System.currentTimeMillis();
        String suffix = FileUtil.getSuffix(mf.getOriginalFilename());

        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        Map<String, Object> resultMap = new HashMap<>();
        try {
            Thumbnails.of(inputStream)
                    .scale(1f)
                    .outputQuality(radioValue)
                    .toFile(filePath + File.separator + fileName + ".jpg");
            File newFile = new File(filePath + File.separator + fileName + ".jpg");
            long size = FileUtil.size(newFile);

            if (!"jpg".equals(suffix)) {
                newFile.renameTo(new File(filePath + File.separator + fileName + "." + suffix));
                resultMap.put("filePath", bizPath + File.separator + fileName + "." + suffix);
            } else {
                resultMap.put("filePath", bizPath + File.separator + fileName + ".jpg");
            }
            resultMap.put("size", DataSizeUtil.format(size));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        compressUsageLogService.saveCompressUsageLog(request, "图片压缩");

        return Result.ok(resultMap);
    }

    @RateLimiter
    @PostMapping("/imgResize")
    public Result<?> imgResize(@RequestParam Integer width,
                               @RequestParam Integer height,
                               HttpServletRequest request,
                               HttpServletResponse response) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象
        String bizPath = "fileTools" + File.separator + request.getParameter("biz");
        String filePath = uploadpath + File.separator + bizPath;
        String orgName = mf.getOriginalFilename();
        String fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));

        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        FileOutputStream os = null;
        Map<String, Object> resultMap = new HashMap<>();

        try {
            os = new FileOutputStream(filePath + File.separator + fileName);
            ImgUtil.scale(mf.getInputStream(), os, width, height, null);
            File newFile = new File(filePath + File.separator + fileName);
            long orgSize = mf.getSize();
            long newSize = FileUtil.size(newFile);
            BufferedImage image = ImageIO.read(mf.getInputStream());
            resultMap.put("orgImg", "原图  " + image.getWidth() + "×" + image.getHeight() + "  " + DataSizeUtil.format(orgSize));
            resultMap.put("newImg", "修改后  " + width + "×" + height + "  " + DataSizeUtil.format(newSize));
            resultMap.put("filePath", bizPath + File.separator + fileName);
            resultMap.put("orgName", orgName);
        } catch (Exception e) {
            log.error("预览文件失败" + e.getMessage());
            response.setStatus(404);
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }

        compressUsageLogService.saveCompressUsageLog(request, "图片改尺寸");
        return Result.ok(resultMap);
    }

    @RateLimiter
    @PostMapping("/clearFile")
    public Result<?> clearFile(@RequestBody List<Map<String, Object>> files) {
        try {
            for (Map<String, Object> file : files) {
                FileUtil.del(uploadpath + File.separator + file.get("filePath"));
            }
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return Result.ok();
    }

    @RateLimiter
    @PostMapping("/excelToPdf")
    public Result<?> excelToPdf(HttpServletRequest request,
                                HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象
        String bizPath = "fileTools" + File.separator + request.getParameter("biz");
        String filePath = uploadpath + File.separator + bizPath;
        String orgName = mf.getOriginalFilename();
        String fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + ".pdf";

        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("orgName", orgName);
        resultMap.put("filePath", bizPath + File.separator + fileName);
        resultMap.put("fileName", fileName);
        try {
            ExcelToPdfUtil.excelToPdf(mf.getInputStream(), filePath + File.separator + fileName);
        } catch (Exception e) {
            throw new AntsException("文件转换失败!");
        }

        return Result.ok(resultMap);
    }

    @RateLimiter
    @PostMapping("/docToPdf")
    public Result<?> docToPdf(HttpServletRequest request,
                                  HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象
        String bizPath = "fileTools" + File.separator + request.getParameter("biz");
        String filePath = uploadpath + File.separator + bizPath;
        String orgName = mf.getOriginalFilename();
        String fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + ".pdf";

        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("orgName", orgName);
        resultMap.put("filePath", bizPath + File.separator + fileName);
        resultMap.put("fileName", fileName);
        try {
            DocToPdfUtil.docToPdf(mf.getInputStream(), filePath + File.separator + fileName);
        } catch (Exception e) {
            throw new AntsException("文件转换失败!");
        }

        return Result.ok(resultMap);
    }

}
